package zydhfile

import (
	"fmt"
	"io"
	"mime/multipart"
	"os"
	"strings"
	"time"
)

var DefaultPerm = os.ModeDir | os.ModePerm

// ------------判断------------

/*
FileOrDirPathIsExist  	判断文件/目录是否存在
link 原文链接：https://blog.csdn.net/leo_jk/article/details/118255913
param 	path string 		文件路径
return	bool	返回信息
*/
func FileOrDirPathIsExist(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}

	//IsNotExist，是不是不存在的错误
	//如果返回的错误类型使用os.isNotExist()判断为true，说明文件或者文件夹不存在
	if os.IsNotExist(err) {
		return false
	}
	return false

	//通过stat的isDir还可以判断一个路径是文件夹还是文件
	// f,err:=stat(); f.IsDir()

}

//------------读------------

// GetFileNameByPath 获取文件的name
func GetFileNameByPath(path string) string {
	fo, err := os.Stat(path)
	if err != nil {
		fmt.Println("open file fail ,file path:"+path, err)
		//log.Error("open file fail ,file path:" + path,err)
		return ""
	}
	return fo.Name()
}

// GetFileLastPath 获取文件路径 ./zydh/log/log.txt --> ./zydh/log/
func GetFileLastPath(path string) string {
	//分隔
	splice := strings.Split(path, "/")
	return strings.Join(splice[:len(splice)-1], "/")
}

// GetFileSizeByPath 获取文件的大小 单位，字节
func GetFileSizeByPath(path string) int {
	fo, err := os.Stat(path)
	if err != nil {
		//log.Error("open file fail ,file path:" + path,err)
		return 0
	}
	return int(fo.Size())
}

//------------写/创建 file------------

// CreatFile 创建文件
func CreatFile(path string, flag int, perm os.FileMode) (*os.File, error) {
	if flag == 0 {
		flag = os.O_CREATE | os.O_TRUNC | os.O_WRONLY
	}
	if perm == 0 {
		flag = 0666
	}
	file, err := os.OpenFile(path, flag, perm)
	if err != nil {
		return file, err
	}
	return file, nil
}

//------------写/创建 dir------------

/*
MkdirAll  创建完整目录路径，即中间目录不存在的话也一起创建
param 	dirPath string 		文件路径
param 	perm 	uint32 		文件权限 0644
return	bool	返回信息
*/
func MkdirAll(dirPath string, perm os.FileMode) (bool bool, err error) {
	if perm == 0 {
		perm = DefaultPerm
	}
	if err = os.MkdirAll(dirPath, perm); err != nil {
		return false, err
	}
	return true, nil
}

//------------删 file------------

//------------删 dir------------

//------------切割 file------------

/*
FileCutBySize 按文件大小切割  每次记录前判断这个文件的大小
param : path string 文件路径
analysis：

	////os.Rename("./aa/bb/c1/file.go", "./aa/bb/c2/file.go")
	//err := os.Rename(pName,logName)  //会把文件移动到/根目录下
*/
func FileCutBySize(path string, logFileMaxSize int, cutFileFormat string) string {
	//判断文件是否超出大小
	if GetFileSizeByPath(path) >= logFileMaxSize {
		//2.备份  xx.log -> xx.log.back202205071155  // warning.txt.bak20220507122541.973
		//在原目录备份							 /		warning.txt				warning.txt.bak20220507122541.973
		err := os.Rename(GetFileLastPath(path)+"/"+GetFileNameByPath(path), getLogFilePathByTime(path, 1, cutFileFormat))
		if err != nil {
			fmt.Println("zydhfile/file.go->FileCutBySize()  Backup failed,err:", err)
		}
	}
	return path
}

// FileCutByTime 按日期切割
func FileCutByTime(path, cutFileFormat string) string {
	//返回路径
	return getLogFilePathByTime(path, 2, cutFileFormat)
}

/*
funs : 获取新的日志文件路径
param : path string 原路径
param : scene int 场景 1 按文件大小 2 按日期
param : cutFileFormat string  场景 	//#按日期切割文件的名称时间格式  	cutFileBySizeTimeFormat string
return : string 根据时间拼接的新路径
*/
func getLogFilePathByTime(path string, scene int, cutFileFormat string) string {
	//文件路径和名词
	pName := GetFileNameByPath(path) //warning.txt
	var nowStr, logName string
	if scene == 1 {
		nowStr = time.Now().Format(cutFileFormat)        //20220507122541.973
		logName = fmt.Sprintf("%s.bak%s", pName, nowStr) //拼接一个备份
	} else if scene == 2 {
		nowStr = time.Now().Format(cutFileFormat)      //20220507122541 //按秒分隔
		logName = fmt.Sprintf("[%s]%s", nowStr, pName) //拼接一个备份
	}

	//[2022-05-07-12:25:41]warning.txt
	return GetFileLastPath(path) + "/" + logName
	// ./zydhlog/[2022-05-07-12:25:41]warning.txt
}

//------------存 save file------------

// SaveFile  直接移动 c.SaveUploadedFile()  uploads the form file to specific dst.
func SaveFile(file *multipart.FileHeader, dst string) error {
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, src)
	return err
}
